package parsing.productions;

import java.util.Random;

import parsing.InvalidSyntaxException;
import world.Critter;

public class Action extends MutableNode implements ExecutableNode {
	//invariant for children: empty
	
	public static final int WAIT 	= 0;
	public static final int FORWARD = 1;
	public static final int BACKWARD= 2;
	public static final int LEFT 	= 3;
	public static final int RIGHT 	= 4;
	public static final int EAT 	= 5;
	public static final int ATTACK 	= 6;
	public static final int GROW 	= 7;
	public static final int BUD 	= 8;
	public static final int MATE 	= 9;
	
	/** This action's type. */
	private int type;

	/**
	 * Constructor: creates an instance of Action with one action.
	 * @param act the static constant that describes this Action's action.
	 * Checks: act is one of Action's static constants. (1<=act<=10).
	 */
	public Action(int act) {
		if (!(act <= 9 && act >= 0)) {
			throw new InvalidSyntaxException("The only types this Action can have are 1-10, specified by Action's static constants.");
		}
		type= act;
	}
	
	@Override
	public int size() {
		return 1;
	}

	@Override
	public void prettyPrint(StringBuffer sb) {
		switch(type){
		case WAIT: sb.append("wait "); break;
		case FORWARD: sb.append("forward "); break;
		case BACKWARD: sb.append("backward "); break;
		case LEFT: sb.append("left "); break;
		case RIGHT: sb.append("right "); break;
		case EAT: sb.append("eat "); break;
		case ATTACK: sb.append("attack "); break;
		case GROW: sb.append("grow "); break;
		case BUD: sb.append("bud "); break;
		case MATE: sb.append("mate "); break;
		}
	}

	@Override
	public void mutate(Program genome) {
		Random rnd = new Random();
		int newType;
		do{
			newType = rnd.nextInt(10);
		} while (newType == type);
//		StringBuffer sb = new StringBuffer();
//		sb.append("Action ");
//		prettyPrint(sb);
		type = newType;
//		sb.append("was changed to ");
//		prettyPrint(sb);
//		System.out.println(sb);
	}

	@Override
	public Node duplicate() {
		return new Action(type);
	}

	/**
	 * Checks if this Action is the same as n
	 * @param n the node to check against
	 * @return true if n is an Action and its type is the same as this one's
	 */
	@Override
	public boolean equals(Node n){
		if(!(n instanceof Action))
			return false;
		Action aNode = (Action) n;
		if(type != aNode.type)
			return false;
		return true;
	}

	@Override
	public boolean execute(Critter c) {
		c.takeSpecifiedAction(type);
		return true;
	}
}
